package com.example.musicplayer;

import android.content.Context;
import android.content.SharedPreferences;

import com.example.musicplayer.commonUtils.StringUtil;
import com.example.musicplayer.musicClass.MusicInfo;
import com.example.musicplayer.user.User;

import java.util.ArrayList;
import java.util.List;

public class MusicScoreManager {
    public static final String SCORE_LYRIC = "lyric_";
    public static final String SCORE_MELODY = "melody_";
    public static final String SCORE_ARRANGEMENT = "arrangement_";
    public static final String SCORE_FAVOR = "favor_";
    public static final String SORT_TYPE = "sortType";
    public static final String SORT_REVERSE = "sortReverse";
    public static final String ONLY_SCORED = "onlyScored";

    public static final int SORT_DEFAULT = 1;
    public static final int SORT_LYRIC = 2;
    public static final int SORT_MELODY = 3;
    public static final int SORT_ARRANGEMENT = 4;
    public static final int SORT_FAVOR = 5;
    public static final int SORT_FINAL = 6;

    private static final String PREFERENCE_NAME_PREFIX = "preference_music_score_";
    private static MusicScoreManager sInstance;
    private static SharedPreferences sPreferences;
    private static List<MusicScoreInfo> sScoreList;
    private static boolean sInitialized;
    private static int sSortType;
    private static boolean sSortReverse;
    private static boolean sOnlyScored;

    private MusicScoreManager() {
        String preferenceName = PREFERENCE_NAME_PREFIX + User.getInstance().getUserId();
        sPreferences = MusicPlayerApplication.getInstance().getSharedPreferences(preferenceName, Context.MODE_PRIVATE);
        sScoreList = new ArrayList<>();
        sInitialized = false;
        //read sort type
        sSortType = sPreferences.getInt(SORT_TYPE, SORT_DEFAULT);
        sSortReverse = sPreferences.getBoolean(SORT_REVERSE, false);
        sOnlyScored = sPreferences.getBoolean(ONLY_SCORED, false);
    }

    public static MusicScoreManager getInstance() {
        User user = User.getInstance();
        if (user == null) {
            return null;
        }
        if (sInstance == null) {
            sInstance = new MusicScoreManager();
        }
        return sInstance;
    }

    public List<MusicScoreInfo> getScoreList() {
        return sScoreList;
    }

    public void init() {
        sScoreList.clear();
        List<MusicInfo> list = MusicInfo.getLocalMusic();
        for (int i = 0; i < list.size(); i++) {
            MusicScoreInfo temp = read(list.get(i).getId());
            if (temp != null) {
                sScoreList.add(temp);
            }
        }
        sInitialized = true;
    }

    public void destroy() {
        sScoreList.clear();
        sInitialized = false;
    }

    public MusicScoreInfo read(int musicId) {
        if (!MusicInfo.has(musicId)) {
            return null;
        }
        if (sInitialized) {
            for (int i = 0; i < sScoreList.size(); i++) {
                if (sScoreList.get(i).getID() == musicId) {
                    return sScoreList.get(i);
                }
            }
            return null;
        } else {
            String key = SCORE_LYRIC + musicId;
            float lyric = sPreferences.getFloat(key, 0f);
            key = SCORE_MELODY + musicId;
            float melody = sPreferences.getFloat(key, 0f);
            key = SCORE_ARRANGEMENT + musicId;
            float arrangement = sPreferences.getFloat(key, 0f);
            key = SCORE_FAVOR + musicId;
            float favor = sPreferences.getFloat(key, 0f);
            return new MusicScoreInfo(musicId, lyric, melody, arrangement, favor);
        }
    }

    public int getSortType() {
        return sSortType;
    }

    public void setSortType(int sortType) {
        int type = sortType;
        if (sortType < SORT_DEFAULT || sortType > SORT_FINAL) {
            type = SORT_DEFAULT;
        }
        if (sSortType != type) {
            sSortType = type;
            sPreferences.edit().putInt(SORT_TYPE, type).apply();
        }
    }

    public boolean isSortReverse() {
        return sSortReverse;
    }

    public void setSortReverse(boolean sortReverse) {
        if (sSortReverse != sortReverse) {
            sSortReverse = sortReverse;
            sPreferences.edit().putBoolean(SORT_REVERSE, sortReverse).apply();
        }
    }

    public boolean isOnlyScored() {
        return sOnlyScored;
    }

    public void setOnlyScored(boolean onlyScored) {
        if (sOnlyScored != onlyScored) {
            sOnlyScored = onlyScored;
            sPreferences.edit().putBoolean(ONLY_SCORED, onlyScored).apply();
        }
    }

    public static class MusicScoreInfo {
        private static final float WEIGHT_LYRIC = 0.1f;
        private static final float WEIGHT_MELODY = 0.3f;
        private static final float WEIGHT_ARRANGEMENT = 0.25f;
        private static final float WEIGHT_FAVOR = 0.35f;

        private final int ID;
        private float mLyric;
        private float mMelody;
        private float mArrangement;
        private float mFavor;
        private float mFinal;

        public MusicScoreInfo(int id, float lyric, float melody, float arrangement, float favor) {
            ID = id;
            mLyric = lyric;
            mMelody = melody;
            mArrangement = arrangement;
            mFavor = favor;
            updateFinal();
        }

        public void setLyric(float lyric) {
            mLyric = lyric;
            updateFinal();
            String key = SCORE_LYRIC + ID;
            sPreferences.edit().putFloat(key, mLyric).apply();
        }

        public float getLyric() {
            return mLyric;
        }

        public void setMelody(float melody) {
            mMelody = melody;
            updateFinal();
            String key = SCORE_MELODY + ID;
            sPreferences.edit().putFloat(key, mMelody).apply();
        }

        public float getMelody() {
            return mMelody;
        }

        public void setArrangement(float arrangement) {
            mArrangement = arrangement;
            updateFinal();
            String key = SCORE_ARRANGEMENT + ID;
            sPreferences.edit().putFloat(key, mArrangement).apply();
        }

        public float getArrangement() {
            return mArrangement;
        }

        public void setFavor(float favor) {
            mFavor = favor;
            updateFinal();
            String key = SCORE_FAVOR + ID;
            sPreferences.edit().putFloat(key, mFavor).apply();
        }

        public float getFavor() {
            return mFavor;
        }

        public float getFinal() {
            return mFinal;
        }

        public int getID() {
            return ID;
        }

        private void updateFinal() {
            mFinal = mLyric * WEIGHT_LYRIC + mMelody * WEIGHT_MELODY + mArrangement * WEIGHT_ARRANGEMENT + mFavor * WEIGHT_FAVOR;
            mFinal = StringUtil.formatFloat_3(mFinal);
        }
    }
}